package com.mvp.lt.airlineview;

import android.graphics.Color;
import android.graphics.Point;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;

import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapView;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.Polygon;
import com.amap.api.maps.model.PolygonOptions;
import com.amap.api.maps.model.Polyline;
import com.amap.api.maps.model.PolylineOptions;
import com.amap.api.maps.model.Text;
import com.amap.api.maps.model.TextOptions;
import com.tbruyelle.rxpermissions2.RxPermissions;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity implements AMap.OnMapClickListener {


    @BindView(R.id.amap)
    MapView mMapView;
    public AMap aMap;

    @BindView(R.id.clear)
    Button mClear;

    @BindView(R.id.currentPointIndex)
    SeekBar currentPointIndex;

    @BindView(R.id.lineRote)
    SeekBar lineRote;

    @BindView(R.id.spaceSeekbar)
    SeekBar spaceSeekbar;

    @BindView(R.id.polygonRote)
    SeekBar polygonRote;

    private RxPermissions mRxPermissions;


    /**
     * 航线间隔
     */
    int space = 20;
    /**
     *  航线 角度
     */
    private int currentHeadDeg = 0;
    /**
     * 飞行 航点集合
     */
    private List<LatLng> mListPolylines;
    /**
     * 拐角点 Marker  列表
     */
    private List<Marker> cornerMakerList = new ArrayList<>();

    /**
     * 拐角点  LatLng 列表
     */
    public List<LatLng> cornerLatLngList = new ArrayList<>();

    /**
     *  ??
     */
    private List<LatLng> rPolygons;

    /**
     * 多边形 - 边框
     */
    public Polygon mPolygon = null;
    /**
     * 组成外接矩形的 5 个点  , 用来辅助 多边形绘制
     */
    List<LatLng> mBoundsEWSNLatLng;
    /**
     * 组成外接矩形的 5 个点  , 用来辅助  航线 绘制
     */
    List<LatLng> mRBoundsEWSNLatLng;

    /**
     * 只有两个点时的那条线
     */
    public Polyline mPolyline;
    /**
     * 已经飞过的航线
     */
    private Polyline mHangXianPolyline2;
    /**
     * 还没飞过的航线
     */
    private Polyline mHangXianPolyline1;
    /**
     * 记录点按下的顺序 ，为了撤销点的操作
     */
    private List<Integer> mIntegerList = new ArrayList<>();
    /**
     * 记录点按下的顺序 ，为了撤销点的操作
     */
    private int lastMarkerLatlngId = 0;

    /**点与点之间的距离*/
    private List<Text> mDistanceText = new ArrayList<>();




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        initView(savedInstanceState);
    }


    private void initView(Bundle savedInstanceState) {

        currentPointIndex.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                updateDoubleSeekbarFlyWayPoint(seekBar.getProgress());  // 测试  // 重绘 已飞、待飞航线
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {    }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });


        lineRote.setMax(360);
        lineRote.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                currentHeadDeg =  progress ;
                drawFlyLines(); // 旋转航线角度
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                updateSpaceLine() ;
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });



        spaceSeekbar.setMax(100);
        spaceSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                space =  progress ;
                updateSpaceLine() ;
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                updateSpaceLine() ;
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

        polygonRote.setMax(360);
        polygonRote.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                currentHeadDeg =  progress - latestProgress  ;
                MyMapTool.e("2角度 = "+ currentHeadDeg);
                cornerLatLngList = MyMapTool.createRotatePolygon(cornerLatLngList, mBoundsEWSNLatLng.get(0), currentHeadDeg);
                mPolygon = drawPolygonOptions(cornerLatLngList);
                latestProgress = progress ;
        }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                clearnCornerPoint() ; //
                updateSpaceLine() ;
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                drawWaypointOrcPicture();
                clearAndRedrawCornerPoint () ;
            }
        });




        mMapView.onCreate(savedInstanceState);
        initMap();

        mClear.setOnClickListener( onClickListener);
    }


    private View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.clear:
                    clearLine();
                    break;


                default:
                    break;
            }

        }
    };

    private void updateSpaceLine() {


        Double latlines[] = MyMapTool.createLats(mRBoundsEWSNLatLng, space);

        int xxx = (int) Math.ceil(latlines[0]);
        List<LatLng> lines;
        List<LatLng> polylines = new ArrayList<>();

        for (int i = 1; i < xxx + 1; i++) {
            lines = new ArrayList<>();
            double fen = (latlines[1]) / 3 * 2;
            for (int j = 0; j < rPolygons.size(); j++) {
                int si = MyMapTool.sint(j + 1, rPolygons.size());
                LatLng checklatlng = MyMapTool.createInlinePoint(rPolygons.get(j), rPolygons.get(si),
                        mRBoundsEWSNLatLng.get(1).latitude + fen - i * latlines[1]);
                if (checklatlng != null) {
                    lines.add(checklatlng);
                }
            }
            if (lines.size() < 2) {
                continue;
            }
            if (lines.get(0) == lines.get(1)) {
                continue;
            }
            if (i % 2 == 0) {
                double min2 = Math.min(lines.get(0).longitude, lines.get(1).longitude);
                LatLng latLng1 = new LatLng(lines.get(0).latitude, min2);


                double max1 = Math.max(lines.get(0).longitude, lines.get(1).longitude);
                LatLng latLng2 = new LatLng(lines.get(0).latitude, max1);
                //
                polylines.add(latLng1);
                polylines.add(latLng2);
            } else {
                double max1 = Math.max(lines.get(0).longitude, lines.get(1).longitude);
                LatLng latLng1 = new LatLng(lines.get(0).latitude, max1);


                double min2 = Math.min(lines.get(0).longitude, lines.get(1).longitude);
                LatLng latLng2 = new LatLng(lines.get(0).latitude, min2);
                polylines.add(latLng1);
                polylines.add(latLng2);
            }
            mListPolylines = MyMapTool.createRotatePolygon(polylines, mBoundsEWSNLatLng.get(0), currentHeadDeg);
            currentPointIndex.setMax(mListPolylines.size());
            MyMapTool.e("1航点个数="+ mListPolylines.size());

        }
        //划线
        updateDoubleSeekbarFlyWayPoint(currentPointIndex.getProgress());// 更新space
    }



    int latestProgress ;
    private void updateDoubleSeekbarFlyWayPoint(Integer currentPostion) {

        MyMapTool.e("航线飞行 "+ currentPostion +"  /"+ currentPointIndex.getMax());

        if (mHangXianPolyline1 != null) {
            mHangXianPolyline1.remove();
        }

        if (mHangXianPolyline2 != null) {
            mHangXianPolyline2.remove();
        }

        List<LatLng> flied = new ArrayList<>();

        for (int i = 0; i <= currentPostion; i++) {
            if (i < currentPostion) {
                flied.add(mListPolylines.get(i));
            }
        }


       mHangXianPolyline1 = aMap.addPolyline(new PolylineOptions()
                .addAll(mListPolylines)
                .color(Color.GREEN)
                .width(5));


        mHangXianPolyline2 = aMap.
                addPolyline(new PolylineOptions()
                        .addAll(flied)
                        .color(Color.RED)
                        .width(5));



    }


    /**
     * 获取 当前点 到所有直线的距离 集合
     */
    private List<Double> getPointToLineDistances(LatLng latLng, List<LatLng> latLngsList) {
        List<Double> distanceList = new ArrayList<>();
        for (int i = 0; i < latLngsList.size(); i++) {
            LatLng latLng1, latLng2;
            if (i == latLngsList.size() - 1) {
                latLng1 = latLngsList.get(i);
                latLng2 = latLngsList.get(0);
            } else {
                latLng1 = latLngsList.get(i);
                latLng2 = latLngsList.get(i + 1);
            }
            //多边形内
            distanceList.add(MyMapTool.PointToSegDist(
                    latLng.longitude, latLng.latitude,
                    latLng1.longitude, latLng1.latitude,
                    latLng2.longitude, latLng2.latitude));
        }
        return distanceList;
    }


    /**
     * 当前添加点有效 ，加入集合
     */
    private void addLatLngToRecord(int postion, LatLng latLng) {
        lastMarkerLatlngId = postion;
        cornerLatLngList.add(postion, latLng);
        mIntegerList.add(lastMarkerLatlngId);
    }


    /**
     * 获取 中心点 到由其他点两两组成的直线的距离 的最短距离 的索引
     */
    private int getMinDistanceIndexOfCenterPointToOtherPoints(List<LatLng> latLngsList, LatLng centerLatlng) {
        LatLng latLng3, latLng4;
        List<LatLng> latLngs = new ArrayList<>();
        int count = latLngsList.size();
        for (int j = 0; j < count; j++) {
            if (j == count - 1) {
                latLng3 = latLngsList.get(j);
                latLng4 = latLngsList.get(0);
            } else {
                latLng3 = latLngsList.get(j);
                latLng4 = latLngsList.get(j + 1);
            }
            latLngs.add(MyMapTool.getMidLatLng(latLng3, latLng4));
        }
        List<Float> integerList = new ArrayList<>();
        for (int j = 0; j < latLngs.size(); j++) {
            integerList.add(MyMapTool.distance(latLngs.get(j), centerLatlng));
        }
        float minDistance = Collections.min(integerList);
        int postion = integerList.indexOf(minDistance);
        return postion;
    }

    private void procePolygons(LatLng latLng) {

        if (mPolygon.contains(latLng)) {
            //在多边形内
            List<Double> distanceList = getPointToLineDistances(latLng, cornerLatLngList);
            double x = Collections.min(distanceList);
            int index = distanceList.indexOf(x);
            addLatLngToRecord(index + 1, latLng);
        } else {
            //在多边形外
            int count = cornerLatLngList.size();
            LatLng centerLatlng = mBoundsEWSNLatLng.get(0);
            for (int i = 0; i < count; i++) {
                if (i == count - 1) {
                    boolean iscross = MyMapTool.doIntersect(
                            MyMapTool.latlng2px(aMap, centerLatlng),
                            MyMapTool.latlng2px(aMap, latLng),
                            MyMapTool.latlng2px(aMap, cornerLatLngList.get(i)),
                            MyMapTool.latlng2px(aMap, cornerLatLngList.get(0)));
                    if (iscross) {
                        addLatLngToRecord(i + 1, latLng);
                        break;
                    } else {
                        int postion = getMinDistanceIndexOfCenterPointToOtherPoints(cornerLatLngList, centerLatlng);
                        addLatLngToRecord(postion + 1, latLng);

                    }
                } else {
                    boolean iscross = MyMapTool.doIntersect(
                            MyMapTool.latlng2px(aMap, centerLatlng),
                            MyMapTool.latlng2px(aMap, latLng),
                            MyMapTool.latlng2px(aMap, cornerLatLngList.get(i)),
                            MyMapTool.latlng2px(aMap, cornerLatLngList.get(i + 1)));
                    if (iscross) {
                        addLatLngToRecord(i + 1, latLng);
                        break;
                    }
                }

            }
        }
    }


    private void proceLineOrOnePoint(LatLng latLng) {
        cornerLatLngList.add(latLng);
        lastMarkerLatlngId = cornerLatLngList.size() - 1;
        mIntegerList.add(lastMarkerLatlngId);
    }


    @Override
    public void onMapClick(LatLng latLng) {

        if (cornerLatLngList.size() >= 3) {
            procePolygons(latLng);
        } else {
            proceLineOrOnePoint(latLng);
        }

        clearAndRedrawCornerPoint() ; //  新赠 拐点时 ，重绘所有拐点图标
        drawWaypointOrcPicture(); // 新赠拐点时重绘航线
    }


    /**
     * 绘制 多边形 、 距离、 航线 等
     */
    public void drawWaypointOrcPicture() {
        //##   绘制 直线 或多边形
        if (cornerLatLngList.size() > 2) {
            mPolygon = drawPolygonOptions(cornerLatLngList);
        } else {
            mPolyline = drawPolyLineOptions(cornerLatLngList);
        }


        //## 绘制距离
        for (Text text : mDistanceText) {
            if (text != null) {
                text.destroy();
            }
        }
        mDistanceText.clear();
        for (int i = 0; i < cornerLatLngList.size(); i++) {
            LatLng latLng1, latLng2;
            if (i == cornerLatLngList.size() - 1) {
                latLng1 = cornerLatLngList.get(i);
                latLng2 = cornerLatLngList.get(0);
            } else {
                latLng1 = cornerLatLngList.get(i);
                latLng2 = cornerLatLngList.get(i + 1);
            }
            float distance = (float) (Math.round(AMapUtils.calculateLineDistance(latLng1, latLng2) * 10)) / 10;
            LatLng mediaLatlng = MyMapTool.getMidLatLng(latLng1, latLng2);
            mDistanceText.add(aMap.addText(new TextOptions().position(mediaLatlng).fontColor(Color.RED).backgroundColor(Color.WHITE).text(distance + "米")));

        }

        //##  绘制 实际的飞行航线
        drawFlyLines() ; // 与多边形一起绘制

    }


    /**
     * 绘制飞行航线
     */
    private void drawFlyLines(){
        if (mHangXianPolyline1 != null) {
            mHangXianPolyline1.remove();
        }
        if (mHangXianPolyline2 != null) {
            mHangXianPolyline2.remove();
        }

        if (cornerLatLngList.size() < 3) {
            return;
        }

        mBoundsEWSNLatLng = MyMapTool.createPolygonBounds(cornerLatLngList);
        rPolygons = MyMapTool.createRotatePolygon(cornerLatLngList, mBoundsEWSNLatLng.get(0), -currentHeadDeg);
        mRBoundsEWSNLatLng = MyMapTool.createPolygonBounds(rPolygons);
        Double latlines[] = MyMapTool.createLats(mRBoundsEWSNLatLng, space);

        // 对浮点数向上取整
        int xxx = (int) Math.ceil(latlines[0]);
        List<LatLng> lines;
        List<LatLng> polylines = new ArrayList<>();

        for (int i = 1; i < xxx + 1; i++) {
            lines = new ArrayList<>();
            double fen = (latlines[1]) / 3 * 2;

            for (int j = 0; j < rPolygons.size(); j++) {
                int si = MyMapTool.sint(j + 1, rPolygons.size());

                LatLng checklatlng = MyMapTool.createInlinePoint(rPolygons.get(j), rPolygons.get(si), mRBoundsEWSNLatLng.get(1).latitude + fen - i * latlines[1]);
                if (checklatlng != null) {
                    lines.add(checklatlng);
                }
            }
            if (lines.size() < 2) {
                continue;
            }
            if (lines.get(0) == lines.get(1)) {
                continue;
            }
            if (i % 2 == 0) {
                double min2 = Math.min(lines.get(0).longitude, lines.get(1).longitude);
                LatLng latLng1 = new LatLng(lines.get(0).latitude, min2);
                double max1 = Math.max(lines.get(0).longitude, lines.get(1).longitude);
                LatLng latLng2 = new LatLng(lines.get(0).latitude, max1);
                //
                polylines.add(latLng1);
                polylines.add(latLng2);
            } else {
                double max1 = Math.max(lines.get(0).longitude, lines.get(1).longitude);
                LatLng latLng1 = new LatLng(lines.get(0).latitude, max1);
                double min2 = Math.min(lines.get(0).longitude, lines.get(1).longitude);
                LatLng latLng2 = new LatLng(lines.get(0).latitude, min2);
                polylines.add(latLng1);
                polylines.add(latLng2);
            }
            mListPolylines = MyMapTool.createRotatePolygon(polylines, mBoundsEWSNLatLng.get(0), currentHeadDeg);
            currentPointIndex.setMax(mListPolylines.size());
            MyMapTool.e("2航点个数="+ mListPolylines.size());

        }

        updateDoubleSeekbarFlyWayPoint(currentPointIndex.getProgress()); // 重绘 已飞、待飞航线


    }


    /**
     * 大于等于三个点。  绘制多边形 。
     */
    public Polygon drawPolygonOptions(List<LatLng> linelatLngs ) {
        if (mPolyline != null) {
            mPolyline.remove();
        }

        if (mPolygon != null) {
            mPolygon.remove();
        }


        PolygonOptions polygonOptions = new PolygonOptions();
        polygonOptions.addAll(linelatLngs);
        polygonOptions.strokeWidth(5)
                .strokeColor(Color.YELLOW)
                .fillColor(Color.YELLOW);
        return aMap.addPolygon(polygonOptions);
    }

    /**
     * 小于三个点 ， 绘制 线条
     */
    private Polyline drawPolyLineOptions(List<LatLng> linelatLngs) {
        if (mPolyline != null) {
            mPolyline.remove();
        }

        PolylineOptions polylineOptions = new PolylineOptions();
        polylineOptions.addAll(linelatLngs);
        polylineOptions.width(5)
                .color(Color.YELLOW);
        return aMap.addPolyline(polylineOptions);
    }


    /**
     * 添加 拐角点
     */
    public void addRangeMarkerToMap(LatLng latLng, int id) {
        View view = getLayoutInflater().inflate(R.layout.way_instrest_point_marker, null);
        TextView textView = view.findViewById(R.id.instrest_marker_index_number);
        textView.setText(String.valueOf(id + 1));

        BitmapDescriptor markerIcon = BitmapDescriptorFactory.fromView(view);
        final MarkerOptions markerOptions = new MarkerOptions().position(latLng).icon(markerIcon).zIndex(2);
        Marker marker = aMap.addMarker(markerOptions);
        marker.setAnchor(0.5f, 0.9f);
        marker.setDraggable(true);
        marker.setSnippet(String.valueOf(id));
        cornerMakerList.add(marker);
    }






    private void initMap() {
        if (aMap == null) {
            aMap = mMapView.getMap();
            aMap.setOnMapClickListener(MainActivity.this);
        }

        aMap.moveCamera(CameraUpdateFactory.zoomTo(17));
        aMap.getUiSettings().setZoomGesturesEnabled(true);
        aMap.getUiSettings().setScaleControlsEnabled(true);
        aMap.getUiSettings().setRotateGesturesEnabled(true);

        //拖拽事件
        aMap.setOnMarkerDragListener(new AMap.OnMarkerDragListener() {
            @Override
            public void onMarkerDragStart(Marker marker) {
            }

            @Override
            public void onMarkerDrag(Marker marker) {
                // 边界拐角点
                int s = Integer.parseInt(marker.getSnippet()); // 获取Marker 覆盖物的文字片段
                cornerLatLngList.set(s, marker.getPosition());
                mPolygon = drawPolygonOptions(cornerLatLngList);


            }

            @Override
            public void onMarkerDragEnd(Marker marker) {
               // 边界拐角点
                int s = Integer.parseInt(marker.getSnippet());
                cornerLatLngList.set(s, marker.getPosition());

                clearAndRedrawCornerPoint () ; // 拖动结束  重绘拐点
                drawWaypointOrcPicture(); // 拖动结束 时重绘航线
            }
        });



        aMap.setOnMapTouchListener(new AMap.OnMapTouchListener() {
            @Override
            public void onTouch(MotionEvent motionEvent) {
                Point point = new Point( (int)(motionEvent.getX()),(int) (motionEvent.getY()));
                LatLng latlng = aMap.getProjection().fromScreenLocation(point);
                switch (motionEvent.getAction()){
                    case MotionEvent.ACTION_DOWN :
                       if(cornerLatLngList.size() >= 3 &&  mPolygon.contains(latlng) ){
                           canMoving = true ;
                            aMap.getUiSettings().setScrollGesturesEnabled(false);
                            lastx =  motionEvent.getX();
                            lasty = motionEvent.getY();
                        }

                        break;
                    case MotionEvent.ACTION_MOVE:
                        if(canMoving){
                            offsetx = motionEvent.getX() - lastx;
                            offsety = motionEvent.getY() - lasty;
                            lastx =  motionEvent.getX();
                            lasty = motionEvent.getY();
                            clearnCornerPoint() ; //
                            updateOverlayByPolygon(offsetx,offsety);
                        }


                        break;
                    case MotionEvent.ACTION_UP:

                        if(canMoving){
                            clearAndRedrawCornerPoint () ; //  平移 结束  重绘拐点
                            drawWaypointOrcPicture(); // 平移多边形
                        }
                        canMoving =false ;
                        aMap.getUiSettings().setScrollGesturesEnabled(true);
                        break;
                    default:
                        break;
                }

            }
        });

        aMap.setOnMarkerClickListener(new AMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {
                // 点击时 不要显示 marker的信息
                marker.hideInfoWindow();
                return true;
            }
        });

    }


    private void clearnCornerPoint(){
        for (Marker marker  : cornerMakerList) {
            if(marker!=null){
                marker.remove();
            }
        }
        cornerMakerList.clear();
    }

    /**
     *  清除 、 重绘 拐角 图标
     */
    private void clearAndRedrawCornerPoint(){
        clearnCornerPoint();
        for (int i = 0; i < cornerLatLngList.size(); i++) {
            addRangeMarkerToMap(cornerLatLngList.get(i), i); // 拖动结束时 ，重绘拐点图标
        }
    }

    private boolean canMoving =false ;
    private float offsetx,offsety , lastx,lasty;
    /**
     * 根据偏移量更新显示位置
     */
    public void updateOverlayByPolygon(float offsetx,float offsety){
        cornerLatLngList =  MyMapTool.getLatLngByOffset(aMap, cornerLatLngList,offsetx,offsety);
        mPolygon = drawPolygonOptions(cornerLatLngList);

    }

    private void clearLine() {

        // 清除 距离信息
        for (int i = 0; i < mDistanceText.size(); i++) {
            mDistanceText.get(i).destroy();
        }
        mDistanceText.clear();

        // 清除边界多边形
        if (mPolygon != null) {
            mPolygon.remove();
        }

        // 清除只有2个点时的线条
        if (mPolyline != null) {
            mPolyline.remove();
        }

        // 清除航线
        if (mHangXianPolyline1 != null) {
            mHangXianPolyline1.remove();
        }
        if (mHangXianPolyline2 != null) {
            mHangXianPolyline2.remove();
        }

        // 清除拐点marker
        for (int i = 0; i < cornerMakerList.size(); i++) {
            cornerMakerList.get(i).remove();
        }
        cornerMakerList.clear();

        // 清除拐点坐标
        cornerLatLngList.clear();

    }



}
